package com.example.service;

import com.example.config.MinioConfig;
import com.example.exception.BusinessException;
import io.minio.*;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * MinIO服务类
 * 处理文件上传、下载、删除等操作
 */
@Slf4j
@Service
public class MinioService {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig minioConfig;

    /**
     * 检查桶是否存在，不存在则创建
     */
    public void ensureBucketExists() {
        try {
            boolean exists = minioClient.bucketExists(
                    BucketExistsArgs.builder()
                            .bucket(minioConfig.getBucketName())
                            .build()
            );
            
            if (!exists) {
                minioClient.makeBucket(
                        MakeBucketArgs.builder()
                                .bucket(minioConfig.getBucketName())
                                .build()
                );
                log.info("创建MinIO桶成功: {}", minioConfig.getBucketName());
            } else {
                log.debug("MinIO桶已存在: {}", minioConfig.getBucketName());
            }
        } catch (Exception e) {
            log.error("检查或创建MinIO桶失败: {}", e.getMessage(), e);
            throw BusinessException.fileUploadFailed();
        }
    }

    /**
     * 上传文件
     */
    public String uploadFile(MultipartFile file, String folder) {
        try {
            // 确保桶存在
            ensureBucketExists();
            
            // 生成文件名
            String originalFilename = file.getOriginalFilename();
            String fileExtension = getFileExtension(originalFilename);
            String fileName = generateFileName() + fileExtension;
            
            // 按日期和文件夹创建路径
            String dateDir = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            String objectName = folder + "/" + dateDir + "/" + fileName;
            
            // 上传文件
            try (InputStream inputStream = file.getInputStream()) {
                minioClient.putObject(
                        PutObjectArgs.builder()
                                .bucket(minioConfig.getBucketName())
                                .object(objectName)
                                .stream(inputStream, file.getSize(), -1)
                                .contentType(file.getContentType())
                                .build()
                );
            }
            
            log.info("文件上传到MinIO成功: {} -> {}", originalFilename, objectName);
            return objectName;
            
        } catch (Exception e) {
            log.error("文件上传到MinIO失败: {}", file.getOriginalFilename(), e);
            throw BusinessException.fileUploadFailed();
        }
    }

    /**
     * 删除文件
     */
    public void deleteFile(String objectName) {
        try {
            if (objectName == null || objectName.trim().isEmpty()) {
                return;
            }
            
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(minioConfig.getBucketName())
                            .object(objectName)
                            .build()
            );
            
            log.info("从MinIO删除文件成功: {}", objectName);
            
        } catch (Exception e) {
            log.error("从MinIO删除文件失败: {}", objectName, e);
            // 删除失败不抛异常，因为这不是关键操作
        }
    }

    /**
     * 获取文件访问URL
     */
    public String getFileUrl(String objectName) {
        if (objectName == null || objectName.trim().isEmpty()) {
            return "";
        }
        return minioConfig.getUrlPrefix() + objectName;
    }

    /**
     * 获取文件预签名URL（用于临时访问）
     */
    public String getPresignedUrl(String objectName, int expiry) {
        try {
            return minioClient.getPresignedObjectUrl(
                    GetPresignedObjectUrlArgs.builder()
                            .method(io.minio.http.Method.GET)
                            .bucket(minioConfig.getBucketName())
                            .object(objectName)
                            .expiry(expiry)
                            .build()
            );
        } catch (Exception e) {
            log.error("获取预签名URL失败: {}", objectName, e);
            return getFileUrl(objectName);
        }
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null || filename.lastIndexOf('.') == -1) {
            return "";
        }
        return filename.substring(filename.lastIndexOf('.'));
    }

    /**
     * 生成唯一文件名
     */
    private String generateFileName() {
        return UUID.randomUUID().toString().replace("-", "");
    }
} 